import { MongoClient, ObjectId } from "mongodb";
import createError from "http-errors";
import config from "../config/config.js";
import Verify from "../utils/verify.js";
const client = new MongoClient(`mongodb://${config.db.host}:${config.db.port}`);

// 导入其他集合模块
import user from "./user.js";
import vcode from "./vcode.js";
import token from "./token.js";

class Collection extends Verify {
  static active = false;

  static resetActivity() {
    Collection.active = true;
    clearTimeout(Collection.autoCloseTimeout);
    Collection.setAutoCloseTimeout();
  }

  static setAutoCloseTimeout() {
    Collection.autoCloseTimeout = setTimeout(() => {
      if (!Collection.active) {
        client.close();
        Collection.active = false;
        Collection.db = null;
      }
    }, 30000);
  }

  constructor(name, validator) {
    super(validator, true);

    this.collection = null;
    this.name = name;
  }

  async connect() {
    if (!this.collection || !Collection.active) {
      !Collection.active && (await client.connect());
      this.collection = client.db(config.db.database).collection(this.name);
    }
    Collection.resetActivity(); // 重置活动状态
  }

  async insertOne(data) {
    try {
      this.toVerify(data);
      await this.connect();
      data.create_time = Date.now();
      data.update_time = "";
      const res = await this.collection.insertOne(data);
      return res.acknowledged ? res.insertedId : -1;
    } catch (error) {
      throw createError(400, `插入数据失败: ${error.message}`);
    }
  }

  async insertMany(data) {
    try {
      this.toVerifyArray(data);
      await this.connect();
      data = data.map((item) => {
        item.create_time = Date.now();
        item.update_time = "";
        return item;
      });
      const res = await this.collection.insertMany(data);
      return res.acknowledged ? res.insertedIds : -1;
    } catch (error) {
      throw createError(400, `批量插入数据失败: ${error.message}`);
    }
  }

  async deleteOne(query) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      const res = await this.collection.deleteOne(query);
      return res.acknowledged ? res.deletedCount : -1;
    } catch (error) {
      throw createError(400, `删除数据失败: ${error.message}`);
    }
  }

  async deleteMany(query) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      const res = await this.collection.deleteMany(query);
      return res.acknowledged ? res.deletedCount : -1;
    } catch (error) {
      throw createError(400, `批量删除数据失败: ${error.message}`);
    }
  }

  async updateOne(query, data, upsert = false, type = "$set") {
    try {
      this.toVerify(data, false);
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      data.update_time = Date.now();
      const res = await this.collection.updateOne(
        query,
        { [type]: data },
        { upsert }
      );
      return res.acknowledged ? res.matchedCount : -1;
    } catch (error) {
      throw createError(400, `更新数据失败: ${error.message}`);
    }
  }

  async updateMany(query, data, type = "$set") {
    try {
      this.toVerify(data, false);
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      data.update_time = Date.now();
      const res = await this.collection.updateMany(query, { [type]: data });
      return res.acknowledged ? res.matchedCount : -1;
    } catch (error) {
      throw createError(400, `批量更新数据失败: ${error.message}`);
    }
  }

  async findOne(query) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      return await this.collection.findOne(query);
    } catch (error) {
      throw createError(400, `查询数据失败: ${error.message}`);
    }
  }

  async find(query) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      return await this.collection.find(query).toArray();
    } catch (error) {
      throw createError(400, `查询数据失败: ${error.message}`);
    }
  }

  async findSort(query, sort) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      return await this.collection.find(query).sort(sort).toArray();
    } catch (error) {
      throw createError(400, `查询数据失败: ${error.message}`);
    }
  }

  async countDocuments() {
    try {
      await this.connect();
      return await this.collection.countDocuments();
    } catch (error) {
      throw createError(400, `查询数据总数失败: ${error.message}`);
    }
  }

  async findPage(query, skip = 0, limit = 100) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      const [list, total] = await Promise.all([
        this.collection.find(query).skip(skip).limit(limit).toArray(),
        this.collection.countDocuments(query),
      ]);
      return { list, total };
    } catch (error) {
      throw createError(400, `分页查询数据失败: ${error.message}`);
    }
  }

  async findSortPage(query, sort, skip = 0, limit = 100) {
    try {
      await this.connect();
      if (query.id) query._id = new ObjectId(query.id);
      delete query.id;
      const [list, total] = await Promise.all([
        this.collection
          .find(query)
          .sort(sort)
          .skip(skip)
          .limit(limit)
          .toArray(),
        this.collection.countDocuments(query),
      ]);
      return { list, total };
    } catch (error) {
      throw createError(400, `分页查询数据失败: ${error.message}`);
    }
  }
}

process.on("exit", client.close); // 退出时关闭连接

const store = {
  user: new Collection("user", user),
  vcode: new Collection("vcode", vcode),
  token: new Collection("token", token),
};

// let cc = client.db("project").collection("user");
// async function fn() {
//   let data = await cc.find({ _id: new ObjectId('67bb61b17df66815c79aebfa') }).toArray()
//   console.log(data[0]._id.toHexString());
// }
// fn();

export default store;
